﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleData.ObjectModel.Design;
using SimpleData.Infrastructure.Plugins;
using SimpleData.Infrastructure.Provider;
using System.Diagnostics.Contracts;

namespace SimpleData.ObjectModel.Internals
{

    /// <summary>
    /// Realiza a construcao do objeto de validacao do documento
    /// </summary>
	internal sealed class DataObjectValidatorCompiler : IDocumentValidatorFactory
	{

		public DataObjectValidatorCompiler( IProvider<RuleName, IRuleBuilderFactory> ruleBuilderFactory, IObjectModelRepository repository )
		{
			Contract.Requires<ArgumentNullException>( ruleBuilderFactory != null, "ruleBuilderFactory" );
			Contract.Requires<ArgumentNullException>( repository != null, "repository" );

			this.RuleBuilderFactory = ruleBuilderFactory;
			this.Repository = repository;
		}

		public IProvider<RuleName, IRuleBuilderFactory> RuleBuilderFactory
		{
			get;
			private set;
		}

		public IObjectModelRepository Repository
		{
			get;
			private set;
		}

		#region IDataObjectValidatorFactory Members

		/// <summary>
		/// 
		/// </summary>
		/// <param name="name"></param>
		/// <returns></returns>
		public IDocumentValidator Create( SchemaName name )
		{
			// TODO : Colocar em cache o validador gerado

			ValidatorBuilder validatorBuilder = new ValidatorBuilder();
			Schema schema = this.Repository.GetSchema<ToEditFetchStrategy>( name );

			// Inclui as validações dos campos do schema
			foreach ( var field in schema.Fields )
				validatorBuilder.IncludeRule( field );

			// Regras do schema
			validatorBuilder.IncludeRule( schema );

			// Inclui as validações dos campos do schema
			//foreach ( var field in schema.Fields )
			//{
			//    // Inclui a validação do tipo
			//    this.IncludeRule( validatorBuilder, field.Rules.FieldType );
			//    // Inclui a validação do campo
			//    this.IncludeRule( validatorBuilder, field.Rules );
			//}

			// Regras do schema
			//this.IncludeRule( validatorBuilder, schema.Rules );

			//
			return validatorBuilder.Build();
		}

		#endregion


		//private void IncludeRule( ValidatorBuilder validator, IEnumerable<Rule> rules )
		//{
		//    foreach ( var rule in rules )
		//        this.IncludeRule( validator, rule );
		//}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="validator"></param>
		/// <param name="rule"></param>
		//private void IncludeRule( ValidatorBuilder validator, Rule rule )
		//{
		//    //IRuleBuilder ruleBuilder = rule.GetBuilder( this.RuleBuilderFactory );
		//    IRuleBuilder ruleBuilder = this.RuleBuilderFactory.Create( rule );
		//    ruleBuilder.BuildOn( validator );
		//}
	}
}
